package com.yx.frame.builder.code;


import java.util.List;

import com.yx.frame.builder.validate.Validator;
import com.yx.frame.builder.xml.MethodMencacheXml;
import com.yx.frame.builder.xml.MethodParmXml;
import com.yx.frame.builder.xml.MethodXml;
import com.yx.frame.builder.xml.QueryMethodContentXml;
import com.yx.frame.builder.xml.QueryMethodContentXml.QuerySql;

public class QueryMethodBuilder extends MethodBuilder {

	String queryResultsetName = null;

	public QueryMethodBuilder(String className, String shortClassName,
			MethodXml method) throws Exception {
		super(className, shortClassName, method);
		queryResultsetName = this.getMethod().getName() + "Table";
		queryResultsetName = queryResultsetName.replaceFirst(queryResultsetName
				.substring(0, 1), queryResultsetName.substring(0, 1)
				.toUpperCase());
	}

	public StringBuffer getJavaCode() throws Exception {
		
		List<MethodParmXml> methodParms = getMethod().getMethodParms();
		List<QuerySql> querySqlList = ((QueryMethodContentXml) getMethod()
				.getMethodContentXml()).getTransaction();
		StringBuffer code = new StringBuffer();
		code.append("\r\n");
		code.append("	/////////////////////////////////////////////////////////////////////\r\n");
		code.append("	//编号：" + this.getMethod().getId() + "\r\n");
		code.append("	//说明：" + this.getMethod().getComment() + "\r\n");
		code.append("	//作者：" + this.getMethod().getAuthor() + "\r\n");
		code.append("	//日期：" + this.getMethod().getDate() + "\r\n");
		code.append("	/////////////////////////////////////////////////////////////////////\r\n");
		code.append("\r\n");

		code.append("	//外部调用方法，用于客户端远程调用服务\r\n");
		code.append("	public static ServiceResult " + this.getMethod().getName()+ "(User user, JSONObject obj)throws Exception {\r\n");

		//code.append("		String databaseName=\""	+ this.getMethod().getDatabaseName() + "\";\r\n");
		//code.append("		" + getClassName() + " daoControl=new " + getClassName()+ "(databaseName);\r\n");
		for (int i = 0; i < methodParms.size(); i++) {
			MethodParmXml methodParmXml = methodParms.get(i);
			code.append("		String " + methodParmXml.getName()+ "=obj.getString(\"" + methodParmXml.getName()+ "\");\r\n");
			Validator[] validators = methodParmXml.getValidators();
			for (int vIdx = 0; vIdx < validators.length; vIdx++) {
				Validator validator = validators[vIdx];
				code.append("		if(!" + validator.getStaticMethodName() + "("+ methodParmXml.getName() + ")) return new ServiceError(\""+ methodParmXml.getComment() + "要求填写"	+ validator.getComment() + "\");\r\n");
			}
		}
		List<String> queryUserDefineDatasource= ((QueryMethodContentXml) getMethod()
				.getMethodContentXml()).getUserDefineDatasource();
		for(int i=0;i<queryUserDefineDatasource.size();i++){
			code.append("		JSONArray " +queryUserDefineDatasource.get(i)+ "=obj.getJSONArray(\"" + queryUserDefineDatasource.get(i)+ "\");\r\n");
		}
		code.append("		ServiceResult returnObj = new ServiceResult();\r\n");
		if ("true".equals(this.getMethod().getPagination())) {
			code.append("		int pageIndex=Integer.parseInt(obj.getString(\"PageIndex\"));\r\n");
			code.append("		int pageSize=Integer.parseInt(obj.getString(\"PageSize\"));\r\n");
		}
		MethodMencacheXml methodMencacheXml=this.getMethod().getMethodMencacheXml();
		if("true".equals(methodMencacheXml.getCached())||"true".equals(methodMencacheXml.getStaticfile())){
			code.append("		String memcachedKey="+methodMencacheXml.getMencacheKey(getMethod().getId(),getMethod().getPagination())+";\r\n");
		}
		if("true".equals(methodMencacheXml.getCached())){
			code.append("		ServiceResult memcachedJSONObject=getServiceMemStorage(memcachedKey);\r\n");
			code.append("		if(memcachedJSONObject!=null)return memcachedJSONObject;\r\n");
		}
		if("true".equals(methodMencacheXml.getStaticfile())){
			code.append("		ServiceResult staticSaveedJSONObject=getServiceFileStorage(memcachedKey,"+methodMencacheXml.getStaticfileDays()+");\r\n");
			code.append("		if(staticSaveedJSONObject!=null)return staticSaveedJSONObject;\r\n");
		}
		for (int i = 0; i < querySqlList.size(); i++) {
			String daoParmSre = "";
			int sqlIdx = querySqlList.get(i).getIndex();
			for (int j = 0; j < methodParms.size(); j++) {				
				MethodParmXml methodParmXml = methodParms.get(j);
				if(sqlIdx==Integer.parseInt(methodParmXml.getSqlIndex())){
					daoParmSre = daoParmSre + methodParmXml.getName() + ",";	
				}			
			}
			if ("true".equals(this.getMethod().getPagination())) {
				daoParmSre=daoParmSre+"pageIndex,pageSize,";
			}
			if("true".equals(querySqlList.get(i).getUserDefineDatasource())){
				daoParmSre=daoParmSre+"DatasourceOf"+querySqlList.get(i).getName()+",";
			}
			if (daoParmSre.endsWith(",")) {
				daoParmSre = daoParmSre.substring(0, daoParmSre.length() - 1);
			}
			
			code.append("		Table resultSet_" + sqlIdx + "= "+getClassName()+"."+ this.getMethod().getName() + "Of" + querySqlList.get(i).getName() + "("+ daoParmSre + ");\r\n");
			
			//if (querySqlList.size() > 1) {
			code.append("		returnObj.put(\"" + querySqlList.get(i).getName()	+ "\",  resultSet_" + sqlIdx + ");\r\n");
			//} else {
				//code.append("		returnObj=resultSet_" + sqlIdx+ ";\r\n");
			//}
		}
		code.append("		returnObj.setServiceMessage(\"执行成功\");\r\n");
		String callback= ((QueryMethodContentXml) getMethod().getMethodContentXml()).getCallback();
		if(null!=callback&&!"".equals(callback)){
			code.append("		returnObj="+callback+"(user,returnObj);\r\n");
		}
		if("true".equals(methodMencacheXml.getCached())){
			code.append("		setServiceMemStorage(memcachedKey,returnObj,"+methodMencacheXml.getCatcheTimeout()+");\r\n");
		}
		if("true".equals(this.getMethod().getRemoveMemcachedUserLicense())){
			code.append("		user.removeMemStoragedUser();\r\n");
		}
		code.append("		return returnObj;\r\n");
		code.append("	}\r\n");
		for (int i = 0; i < querySqlList.size(); i++) {
			int sqlIdx = querySqlList.get(i).getIndex();
			code.append(getJavaCode(sqlIdx));
		}
		return code;
	}

	public StringBuffer getJavaCode(int sqlIdx) throws Exception {

		String javaSql = ((QueryMethodContentXml) getMethod()
				.getMethodContentXml()).getTransaction().get(sqlIdx - 1)
				.getSql();
		String sqlName= ((QueryMethodContentXml) getMethod()
				.getMethodContentXml()).getTransaction().get(sqlIdx - 1).getName();
		String[] dataSrcList=((QueryMethodContentXml) getMethod()
				.getMethodContentXml()).getTransaction().get(sqlIdx - 1).getDatasource();
		String userDefineDatasource=((QueryMethodContentXml) getMethod()
				.getMethodContentXml()).getTransaction().get(sqlIdx - 1).getUserDefineDatasource();
		if(dataSrcList==null||dataSrcList.length==0){
			dataSrcList=new String[]{""};
		}
		
		String javaParmsStr = "";
		String parmsTypeArray="String[] parmsTypeArray=new String[]{";
		String parmsValueArray="String[] parmsValueArray=new String[]{";
			
		List<MethodParmXml> methodParms = getMethod().getMethodParms();
		for (int i = 0; i < methodParms.size(); i++) {
			MethodParmXml methodParmXml = methodParms.get(i);
			if(sqlIdx==Integer.parseInt(methodParmXml.getSqlIndex())){
				javaParmsStr = javaParmsStr + "String " + methodParmXml.getName()+ ",";
				parmsTypeArray=parmsTypeArray+"\""+methodParmXml.getType()+"\",";
				parmsValueArray=parmsValueArray+methodParmXml.getName()+ ",";
			}			
		}		
		if ("true".equals(getMethod().getPagination())) {
			javaParmsStr = javaParmsStr + "  int pageIndex, int pageSize,";
			parmsTypeArray=parmsTypeArray+"\"Int\",\"Int\",";
			parmsValueArray=parmsValueArray+"String.valueOf(pageIndex),String.valueOf(pageSize),";
		}
		if("true".equals(userDefineDatasource)){
			javaParmsStr = javaParmsStr + "JSONArray DatasourceOf"+sqlName+",";
		}
		if (javaParmsStr.endsWith(",")){
			javaParmsStr = javaParmsStr.substring(0, javaParmsStr.length() - 1);			
		}
		if(parmsTypeArray.endsWith(",")){
			parmsTypeArray = parmsTypeArray.substring(0, parmsTypeArray.length() - 1);
			parmsValueArray = parmsValueArray.substring(0, parmsValueArray.length() - 1);
		}
		parmsTypeArray=parmsTypeArray+"};";
		parmsValueArray=parmsValueArray+"};";
		
		StringBuffer code = new StringBuffer();
		code.append("\r\n");
		code.append("	//内部数据库处理\r\n");
		code.append("	public static Table "+ this.getMethod().getName() + "Of" +sqlName+ "("+ javaParmsStr + ")  throws Exception {\r\n");
		code.append("		String sqlStr=\"" + javaSql + "\";\r\n");
		code.append("		SqlEntry sqlEntry=new SqlEntry(sqlStr);\r\n");	
		code.append("		sqlEntry.setPagable("+this.getMethod().getPagination()+");\r\n");
		code.append("		"+parmsTypeArray+"\r\n");
		code.append("		sqlEntry.setParamType(parmsTypeArray);\r\n");
		code.append("		"+parmsValueArray+"\r\n");
		code.append("		sqlEntry.addParms(parmsValueArray);\r\n");
		if("true".equals(userDefineDatasource)){
			code.append("		Table queryResultTable=null;\r\n");
			code.append("		for(int i=0,len=DatasourceOf"+sqlName+".length();i<len;i++){\r\n");
			code.append("			Sql sqlControl=new Sql(DatasourceOf"+sqlName+".getString(i));\r\n");
			code.append("			if(i==0){\r\n");			
			code.append("				queryResultTable= sqlControl.query(sqlEntry);\r\n");
			code.append("			}else{\r\n");
			code.append("				queryResultTable.copy(sqlControl.query(sqlEntry));\r\n");		
			code.append("			}\r\n");
			code.append("		}\r\n");
		}else{
			for(int i=0;i<dataSrcList.length;i++){			
				if(i==0){
					code.append("		Sql sqlControl=new Sql(\""+dataSrcList[i]+"\");\r\n");
					code.append("		Table queryResultTable= sqlControl.query(sqlEntry);\r\n");
				}else{
					code.append("		sqlControl=new Sql(\""+dataSrcList[i]+"\");\r\n");
					code.append("		queryResultTable.copy(sqlControl.query(sqlEntry));\r\n");				
				}
			}
		}
		int[] unzipCol= ((QueryMethodContentXml) getMethod()
				.getMethodContentXml()).getTransaction().get(sqlIdx - 1).getUnzipcolumnNumber();
		for(int i=0;i<unzipCol.length;i++){
			code.append("		queryResultTable.unzip("+unzipCol[i]+");\r\n");
		}
		code.append("		return queryResultTable;\r\n");
		code.append("	}\r\n");
		code.append("\r\n");
		return code;
	}

	
	public StringBuffer[] getJsWebCode(String jsControlName) throws Exception {
		StringBuffer code = new StringBuffer();		
		String jsParmsStr = "";
		String jsonParm = "";
		String parmInputDiscription="";
		List<MethodParmXml> methodParms = getMethod().getMethodParms();
		for (int i = 0; i < methodParms.size(); i++) {
			MethodParmXml methodParmXml = methodParms.get(i);
			jsParmsStr = jsParmsStr + methodParmXml.getName() + ",";
			jsonParm = jsonParm + methodParmXml.getName() + ":"
					+ methodParmXml.getName() + ",";
			if(methodParmXml.isMutilistType()){
				parmInputDiscription=parmInputDiscription+(i+1)+"、"+methodParmXml.getName()+"："+methodParmXml.getComment()+"&nbsp;-"+methodParmXml.getType()+"数组（"+methodParmXml.getValidator()+"）<br>";
			}else{
				parmInputDiscription=parmInputDiscription+(i+1)+"、"+methodParmXml.getName()+"："+methodParmXml.getComment()+"&nbsp;-"+methodParmXml.getType()+"（"+methodParmXml.getValidator()+"）<br>";
			}
		}

		if ("true".equals(this.getMethod().getPagination())) {
			jsParmsStr = jsParmsStr + "pageIndex,pageSize,";
			jsonParm = jsonParm + "PageIndex:pageIndex,PageSize:pageSize,";
		}
		QueryMethodContentXml queryMethodContentXml=(QueryMethodContentXml)getMethod().getMethodContentXml();
		List<String> userDefDsList=queryMethodContentXml.getUserDefineDatasource();
		for(int i=0;i<userDefDsList.size();i++){
			jsParmsStr = jsParmsStr+userDefDsList.get(i)+",";
			jsonParm = jsonParm +userDefDsList.get(i)+":"+userDefDsList.get(i)+ ",";
		}
		String sampleParmStr=jsParmsStr;
		sampleParmStr=splitParmsHtml(sampleParmStr);
		jsParmsStr = jsParmsStr + "callbackFunction,";
		if (jsParmsStr.endsWith(","))
			jsParmsStr = jsParmsStr.substring(0, jsParmsStr.length() - 1);
		if (jsonParm.endsWith(","))
			jsonParm = jsonParm.substring(0, jsonParm.length() - 1);
		jsonParm = "{" + jsonParm + "}";
		
		List<QuerySql> querySqlList = ((QueryMethodContentXml) getMethod()
				.getMethodContentXml()).getTransaction();
		

		//code.append("\r\n");
		
		StringBuffer returnResulsString=new StringBuffer();
		returnResulsString.append("返回数据：返回数据以SQL查询结果集方式存储，每条查询形成一个结果集，数据按以行数组方式存储<br>\r\n");
		String callBackResoult="";
		String callBackParmStr="";
		for(int i=0;i<querySqlList.size();i++){
			QuerySql querySql=querySqlList.get(i);
			returnResulsString.append("结果集："+querySql.getName()+"为JSON对象数组，每一个数组元素"+querySql.getName()+"[i]均是结构为：{"+querySql.getSqlColums()+"}的JSON对象<br>\r\n");
			callBackResoult=callBackResoult+","+querySql.getName();
			String[] returnKeys=querySql.getSqlColumsArray();
			String returnKeyStr="";
			for(int k=0;k<returnKeys.length;k++){
				returnKeyStr=returnKeyStr+",\""+returnKeys[k]+"\"";
			}
			if(returnKeyStr.length()>1){
				returnKeyStr=returnKeyStr.substring(1);
			}
			callBackParmStr=",jsonData."+querySql.getName()+"";
		}		
		StringBuffer sampleString=new StringBuffer();
		sampleString.append("	"+jsControlName+"." +this.getMethod().getName() +"_"+this.getMethod().getId()+ "("+sampleParmStr+"function(isOK,message"+callBackResoult+"){   <br>\r\n");
		sampleString.append("	    &nbsp;&nbsp;if(isOK){//服务调用成功<br>\r\n");
		sampleString.append("	    &nbsp;&nbsp;}else{//服务调用失败，返回错误信息<br>\r\n");
		sampleString.append("	        &nbsp;&nbsp;&nbsp;&nbsp;var errorMessage=message;<br>\r\n");
		sampleString.append("	    &nbsp;&nbsp;}<br>\r\n");
		sampleString.append("	});\r\n");
		
		StringBuffer html=JsFileWriter.htmlStr(this.getMethod().getIsMobilApp(),""+this.getMethod().getId(),
				this.getMethod().getName()+"_"+this.getMethod().getId() + "("	+ splitParmsHtml(jsParmsStr) + ")", this.getMethod().getComment(), this.getMethod().getAuthor(), this.getMethod().getDate(), parmInputDiscription, returnResulsString.toString(), sampleString.toString());
		//code.append("\r\n");
		code.append("	this." + this.getMethod().getName()+"_"+this.getMethod().getId() + "=function("	+ jsParmsStr + "){");
		code.append("var data = " + jsonParm + ";");
		code.append("this.jsonPost("+this.getMethod().getId()+","+this.getMethod().getAsyncService()+",data,function(jsonData,callback){callback(jsonData.IsOK, jsonData.Message"+callBackParmStr+");},callbackFunction);");
		code.append("};\r\n");
		return new StringBuffer[]{code,html};
	}
	
}
